package com.shjzit.loglib.utils;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadUtils {

    private static final int MAXIMUM_POOL_SIZE = Integer.MAX_VALUE;
    private static final long KEEP_ALIVE_TIME = 10 * 60;
    private ThreadPoolExecutor executor;

    private static class SingletonHolder {
        private static final ThreadUtils INSTANCE = new ThreadUtils();
    }

    private static ThreadUtils getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private ThreadUtils() {
        int corePoolSize = Runtime.getRuntime().availableProcessors() * 2 + 1;
        executor = new ThreadPoolExecutor(
                corePoolSize, //当某个核心任务执行完毕，会依次从缓冲队列中取出等待任务
                MAXIMUM_POOL_SIZE, //5,先corePoolSize,然后new LinkedBlockingQueue<Runnable>(),然后maximumPoolSize,但是它的数量是包含了corePoolSize的
                KEEP_ALIVE_TIME, //表示的是maximumPoolSize当中等待任务的存活时间
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(), //缓冲队列，用于存放等待任务，Linked的先进先出
                Executors.defaultThreadFactory(), //创建线程的工厂
                new ThreadPoolExecutor.AbortPolicy() //用来对超出maximumPoolSize的任务的处理策略
        );
    }

    /**
     * 对外提供的接口，用于执行任务
     *
     * @param runnable
     */
    public static void execute(Runnable runnable) {
        getInstance().doExecute(runnable);
    }

    /**
     * 执行任务
     *
     * @param runnable
     */
    private void doExecute(Runnable runnable) {
        executor.execute(runnable);
    }

    /**
     * 对外提供的接口，用于移除任务
     *
     * @param runnable
     */
    public static void remove(Runnable runnable) {
        getInstance().doRemove(runnable);
    }

    /**
     * 执行移除任务
     *
     * @param runnable
     */
    private void doRemove(Runnable runnable) {
        if (runnable == null) {
            return;
        }
        executor.remove(runnable);
    }

    /**
     * 睡眠一段时间
     *
     * @param millis
     */
    public static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
